# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'
__all__ = []

from ... import formlib as layout
from ... import hint
from ... import pilelib as stack
from ...forms import (canfield as CanfieldLayout, gypsy as GypsyLayout,)
from ...gamelib import info as gi, game
from ...packlib import info as cs
from ...piles import hanafuda as hstack
from ...utillib.misc import kwdefault

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class Sumo(cs.Hanafuda_Deck, game.Game):
    """
    Finish 1 deck by full seq on foundations.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.DoorwayLayout
        - row [8 horz S foundation, vert offset]
        - reserve [1 E 1 W row, no offset]
        - talon [1 NW, no offset]
        - foundation [12 over 2 row N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Rank_Foundation

        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.RankSS_RowStack (base_rank=FIRST)

        Init 6 open card. Build down in rank by same suit. Play any. Base 1st
        rank.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.hanafuda.ReserveStack

        Build any. Play top. Max 1 card.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x18fd1, name='Sumo', category=cs.TYPE_HANAFUDA,
                    game_type=(GT.FREECELL | GT.OPEN), decks=1,
                    skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _layout_ = CanfieldLayout.DoorwayLayout
    _talon_ = stack.InitialDealTalon
    _foundation_ = hstack.Rank_Foundation
    _row_ = Wrap(hstack.RankSS_RowStack, base_rank=cs.FIRST)
    _reserve_ = stack.ReserveStack
    _hint_ = hint.CautiousDefaultHint

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, reserves=2, texts=False, playcards=16)
        return super(Sumo, self)._create_game(**kw)

    def _start(self, rows=6, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 6 ea up.

        .. \_start([rows=6]) -> None
        """
        for i in range(rows - 1):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()


class BigSumo(Sumo):
    """
    Finish 2 deck by full seq on foundations.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.DoorwayLayout
        - row [10 horz S foundation, vert offset]
        - reserve [2 E 2 W row, no offset]
        - talon [1 S, no offset]
        - foundation [16 over 2 row N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Rank_Foundation
        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.RankSS_RowStack (base_rank=FIRST)
        Init 9, 9, 10 ... 10, 9, 9 open card. Build down in rank by same suit.
        Play any. Base 1st rank.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.hanafuda.ReserveStack
        Build any. Play top. Max 1 card.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x18fd2, name='Big Sumo', category=cs.TYPE_HANAFUDA,
                    game_type=(GT.FREECELL | GT.OPEN), decks=2,
                    skill_level=SL.MOSTLY_SKILL, version='0.50fc',
                    altnames=('Sumo (2 Decks)',))
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, reserves=4, playcards=20)
        return super(BigSumo, self)._create_game(self, **kw)

    def _start(self, rows=10, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 9 ea up.
          - s[rows][2:8] 1 ea.

        .. \_start([rows=6]) -> None
        """
        super(BigSumo, self)._start(rows=rows - 1, **kw)
        self.s['talon'].dealRow(rows=self.s['rows'][2:8])


class JustForFun(cs.Hanafuda_Deck, game.Game):
    """
    Finish 1 deck by full seq on foundations.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.gypsy.GypsyLayout
        - row [12 over 2 rows N, vert offset]
        - reserve [2 S, no offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build up in suit by same rank. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.RankSS_RowStack (base_rank=FIRST)

        Init 4 open card. Build up in rank by same suit. Play any. Base
        1st rank.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.hanafuda.ReserveStack

        Build any. Play top. Max 1 card.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x18fd6, name='Just For Fun', category=cs.TYPE_HANAFUDA,
                    game_type=(GT.FREECELL | GT.OPEN), decks=1,
                    skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _layout_ = GypsyLayout.GypsyLayout
    _talon_ = stack.InitialDealTalon
    _foundation_ = hstack.Suit_Foundation
    _row_ = Wrap(hstack.RankSS_RowStack, base_rank=cs.FIRST)
    _reserve_ = stack.ReserveStack

    def _create_game(self, rows=12, reserves=2, texts=False, playcards=22,
                     **kw):
        l, s = self._layout_(self), self.s
        kw.setdefault('bases', l.RANKS)
        l.create(rows=rows, reserves=reserves, texts=texts, playcards=playcards,
                 **kw)
        return super(JustForFun, self)._create_game(*kw)

    def _start(self, rows=4, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~4 ea up.

        .. \_start([rows=4]) -> None
        """
        for i in range(rows - 1):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRowAvail()


class DoubleYourFun(JustForFun):
    """
    Finish 2 deck by full seq on foundations.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.gypsy.GypsyLayout
        - row [18 over 2 rows N, vert offset]
        - reserve [4 S, no offset]
        - talon [1 SE, no offset]
        - foundation [8 over 2 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation
        Build up in suit by same rank. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.RankSS_RowStack (base_rank=FIRST)
        Init all open, min 5 card. Build up in rank by same suit. Play any.
        Base 1st rank.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.hanafuda.ReserveStack
        Build any. Play top. Max 1 card.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x18fdc, name='Double Your Fun',
                    category=cs.TYPE_HANAFUDA, game_type=(GT.FREECELL |
                    GT.OPEN), decks=2, skill_level=SL.MOSTLY_SKILL,
                    version='0.50fc', altnames=('Just For Fun (2 decks)',))
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, rows=18, reserves=4)
        return super(DoubleYourFun, self)._create_game(**kw)


class Firecracker(JustForFun):
    """
    Finish 1 deck by full seq on foundations.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.gypsy.GypsyLayout
        - row [12 over 2 rows N, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build up in suit by same rank. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.RankSS_RowStack (strict=False)

        Init 4 open card. Build up in rank by same suit with trash cards
        swap except Willow. Play any.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x18fd7, name='Firecracker', category=cs.TYPE_HANAFUDA,
                    game_type=(GT.GYPSY | GT.OPEN), decks=1,
                    skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = Wrap(hstack.RankSS_RowStack, strict=False)
    _reserves_ = None

    def _create_game(self, **kw):
        kw.setdefault('reserves', 0)
        return super(Firecracker, self)._create_game(**kw)


class CherryBomb(Firecracker):
    """
    Finish 2 deck by full seq on foundations.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.gypsy.GypsyLayout
        - row [18 over 2 rows N, vert offset]
        - talon [1 S, no offset]
        - foundation [8 over 2 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation
        Build up in suit by same rank. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_RowStack (base_rank=FIRST)
        Init all open, min 5 card. Build up in rank by same suit with trash
        cards swap except Willow. Play any. Base 1st rank.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x18fdd, name='Cherry Bomb', category=cs.TYPE_HANAFUDA,
                    game_type=(GT.GYPSY | GT.OPEN), decks=2,
                    skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('rows', 18)
        return super(CherryBomb, self)._create_game(**kw)


class JapaneseGarden(cs.Hanafuda_Deck, game.Game):
    """
    Finish 1 deck by full seq on foundations.

    Layout
      - row [6 over 2 rows S foundation, horz offset]
      - reserve [12 over 2 rows S row, no offset]
      - talon [1 NW, no offset]
      - foundation [12 over 2 col E, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stack.Rk_RowStack (max_accept=1, max_move=1, max_cards=6,
          base_rank=FIRST, dir=1)

        Init 6 open card. Build down in rank alone. Play top. Base 1st
        rank. Max 6 cards.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack

        Init 1 card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint

    :todo: needs seperate layout
    """
    __info__ = dict(id=0x18fe5, name='Japanese Garden Ⅰ',
                    category=cs.TYPE_HANAFUDA, game_type=(GT.FAN_TYPE | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _talon_ = stack.InitialDealTalon
    _foundation_ = hstack.Rank_Foundation
    _row_ = Wrap(stack.RK_RowStack, max_accept=1, max_move=1, max_cards=6,
                 base_rank=cs.FIRST, dir=1)
    _reserve_ = stack.OpenStack
    _hint_ = hint.CautiousDefaultHint

    def _create_game(self, rows=6, row_cols=3, reserves=12, reserve_cols=6):
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + l.XS * 10, l.YM * 3 + l.YS * 6,)
        x, y = self.width / 2 + l.XM / 2 - l.XS * 3, l.YM
        for (x, y), suit in zip(l.col_block_iter(x, y, l.NSUIT, ncols=6),
                                l.SUIT):
            s['foundations'].append(self._foundation_(x, y, game=self,
                                                   suit=suit))
        x = l.XM
        y += l.YM
        for x, y_ in l.col_block_iter(x, y, rows, ncols=row_cols, xcards=6):
            s['rows'].append(self._row_(x, y_, game=self, offset=(l.XOFFSET, 0)))
        self._set_region(s['rows'], l._region(y=y, h=y_))
        x, y = (self.width - (l.XS * reserve_cols)) / 2, y_
        if self._reserve_ is not None:
            for x, y_ in l.col_block_iter(x, y, reserves, ncols=reserve_cols):
                s['reserves'].append(self._reserve_(x, y_, game=self))
            self._set_region(s['reserves'], l._region(y=y))
        s['talon'] = self._talon_(l.XM, l.YM, game=self)
        l.defaultStackGroups()
        return l

    def _start(self, rows=6, reserves=True, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 6 ea up.
          - s[reserves] 1 ea.

        .. \_start([rows=6, reserves=True]) -> None
        """
        for i in range(rows):
            self.s['talon'].dealRow()
        if reserves:
            self.s['talon'].dealRow(rows=self.s['reserves'])


class JapaneseGardenII(JapaneseGarden):
    """
    Finish 1 deck by full seq on foundations.

    Layout
      - row [6 over 2 rows S foundation, horz offset]
      - reserve [12 over 2 rows S row, no offset]
      - talon [1 NW, no offset]
      - foundation [12 over 2 col E, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.JapaneseGarden_RowStack (max_accept=1,
          max_move=1, max_cards=6, dir=1)

        Init 6 open card. Build down in rank alone from any but another
        row. Play top. Base 1st rank. Max 6 cards.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack

        Init 1 card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x18fe6, name='Japanese Garden Ⅱ',
                    category=cs.TYPE_HANAFUDA, game_type=(GT.FAN_TYPE | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = Wrap(hstack.JapaneseGarden_RowStack, max_accept=1, max_move=1,
                 max_cards=6, dir=1)


class JapaneseGardenIII(JapaneseGardenII):
    """
    Finish 1 deck by full seq on foundations.

    Layout
      - row [8 over 2 rows S foundation, horz offset]
      - talon [1 NW, no offset]
      - foundation [12 over 2 col E, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.JapaneseGarden_RowStack (max_accept=1,
          max_move=1, max_cards=7, base_rank=FIRST, dir=1)

        Init 6 open card. Build down in rank alone from any but another
        row. Play top. Base 1st rank. Max 7 cards.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x18fe9, name='Japanese Garden Ⅲ',
                    category=cs.TYPE_HANAFUDA, game_type=(GT.FAN_TYPE | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = Wrap(hstack.JapaneseGarden_RowStack, max_accept=1, max_move=1,
                 max_cards=7, dir=1)
    _reserve_ = None

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, row_cols=2)
        return super(JapaneseGardenII, self)._create_game(**kw)

    def _start(self, reserves=False, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 6 ea up.

        .. \_start([rows=6, reserves=False]) -> None
        """
        kw.setdefault('reserves', False)
        super(JapaneseGardenII, self)._start(reserves=reserves, **kw)


class SixSages(JapaneseGarden):
    """
    Finish 1 deck by full seq on foundations.

    Layout
      - row [6 over 2 rows S foundation, horz offset]
      - reserve [1 S row, no offset]
      - talon [1 NW, no offset]
      - foundation [12 over 2 col E, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stack.Rk_RowStack (max_accept=1, max_move=1, max_cards=9,
          base_rank=FIRST, dir=1)

        Init 8 open card. Build down in rank alone. Play top. Base 1st
        rank. Max 9 cards.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.ReserveStack

        Build any. Play top. Max 1 card.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x18fe7, name='Six Sages',
                    category=cs.TYPE_HANAFUDA, game_type=(GT.FAN_TYPE | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = Wrap(stack.RK_RowStack, max_accept=1, max_move=1, max_cards=9,
                 base_rank=cs.FIRST, dir=1)
    _reserve_ = stack.ReserveStack

    def _create_game(self, **kw):
        kwdefault(kw, reserves=1, reserve_cols=1)
        return super(SixSages, self)._create_game(**kw)

    def _start(self, rows=8, reserves=False, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 8 ea up.

        .. \_start([rows=8, reserves=False]) -> None
        """
        super(JapaneseGardenII, self)._start(rows=rows, reserves=reserves, **kw)


class SixTengus(SixSages):
    """
    Finish 1 deck by full seq on foundations.

    Layout
      - row [6 over 2 rows S foundation, horz offset]
      - talon [1 NW, no offset]
      - foundation [12 over 2 col E, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.InitialDealTalon

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.Suit_Foundation

        Build down in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stack.Rk_RowStack (max_accept=1, max_move=1, max_cards=9,
          base_rank=FIRST, dir=1)

        Init 8 open card. Build up in rank alone. Play any 2 card. Base
        1st rank. Max 9 cards.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x18fe8, name='Six Tengus',
                    category=cs.TYPE_HANAFUDA, game_type=(GT.FAN_TYPE | GT.OPEN),
                    decks=1, skill_level=SL.MOSTLY_SKILL, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = Wrap(hstack.Rank_RowStack, max_accept=2, max_move=2, max_cards=9,
                 dir=1)
    _reserve_ = None


PROVIDES = [BigSumo, CherryBomb, DoubleYourFun, Firecracker, JustForFun, Sumo,
            JapaneseGarden, JapaneseGardenII, JapaneseGardenIII, SixSages,
            SixTengus]